package android.slc.sys.ui

import android.annotation.SuppressLint
import android.app.Application
import android.slc.appbase.api.slc.SlcApi
import android.slc.appbase.api.slc.callback.SlcObserver
import android.slc.appbase.api.slc.config.ApiConfig
import android.slc.appbase.api.slc.config.ApiSp
import android.slc.appbase.api.slc.utils.IpReckonUtils
import android.slc.appbase.vm.AppBaseViewModel
import android.slc.core.vm.SingleLiveEvent
import android.slc.extras.user.entity.LoginResult
import android.slc.or.SlcCallbackConfig
import android.slc.or.SlcParam
import android.slc.rx.SlcRxJavaUtils
import android.slc.sys.R
import android.slc.sys.repository.service.SearchService
import androidx.databinding.ObservableBoolean
import androidx.databinding.ObservableField
import cn.hutool.core.lang.Validator
import cn.hutool.core.util.ReUtil
import cn.hutool.core.util.StrUtil
import com.blankj.utilcode.constant.RegexConstants
import com.blankj.utilcode.util.*
import me.jessyan.retrofiturlmanager.RetrofitUrlManager

/**
 *
 * @Description:
 * @Author: sunlunchang
 * @CreateDate: 2022/06/29 下午 4:28
 *
 */
class ApiConfigVm(application: Application) : AppBaseViewModel(application) {

    //apply
    val mainSwitchStatus = ObservableBoolean(ApiSp.isApplyCacheApi())

    //service
    val configServiceModeName =
        ObservableField(StringUtils.getStringArray(R.array.api_config_mode_1)[ApiSp.getServiceMode()])
    private var configServiceMode = ApiSp.getServiceMode()
    val configServiceApiAddress = ObservableField(ApiConfig.getInstance().serviceApiAddress)
    val configServiceAutoSearchBtnVisible =
        ObservableBoolean(isAutoMode())


    val showSearchingDialog = SingleLiveEvent<Boolean>()
    val showSearchEndDialog = SingleLiveEvent<String>()
    private var allowedRecursionSearch = false

    private val ipReckonUtils = IpReckonUtils()

    companion object {
        const val TEST_API_USER_NAME = "textApi123"
    }

    private fun isAutoMode(): Boolean {
        return configServiceMode == ApiSp.CONFIG_MODE_AUTO_CURRENT || configServiceMode == ApiSp.CONFIG_MODE_AUTO_LOCAL
    }

    /**
     * 设置服务api模式
     */
    fun setConfigServiceMode(mode: Int, modeName: String) {
        configServiceMode = mode
        configServiceModeName.set(modeName)
        configServiceAutoSearchBtnVisible.set(isAutoMode())
    }

    /**
     * 取消轮询搜索
     */
    fun cancelRecursionSearch() {
        allowedRecursionSearch = false
    }

    /**
     * 自动搜搜APi
     */
    @SuppressLint("MissingPermission")
    fun autoSearchApi() {
        if (!isAutoMode()) {
            return
        }
        val localIp = if (configServiceMode == ApiSp.CONFIG_MODE_AUTO_CURRENT) {
            try {
                ReUtil.get(RegexConstants.REGEX_IP, ApiConfig.getInstance().serviceApiAddress, 0)
            } catch (e: IndexOutOfBoundsException) {
                ToastUtils.showLong(R.string.net_date_sending_data_error_please_check_the_network)
                return
            }
        } else {
            NetworkUtils.getIPAddress(true)
        }
        if (!ReUtil.isMatch(Validator.IPV4, localIp)) {
            ToastUtils.showLong(R.string.net_date_sending_data_error_please_check_the_network)
            return
        }
        ipReckonUtils.setIpGist(localIp, 1)
        ipReckonUtils.setOnlyLastSit(false)
        showSearchingDialog.value = true
        allowedRecursionSearch = true
        recursionSearch()
    }

    /**
     * 递归搜索服务器
     */
    private fun recursionSearch() {
        if (!allowedRecursionSearch) {
            return
        }
        if (!ipReckonUtils.hasNext()) {
            //如果没有下一个信则则通知搜索失败
            searchFinish(StringUtils.getString(R.string.api_label_searching_service_fail))
            return
        }
        //组装的ip
        val nextIp = ipReckonUtils.next()
        val tryApi = RegexUtils.getReplaceAll(
            ApiConfig.getInstance().serviceApiAddress,
            RegexConstants.REGEX_IP,
            nextIp
        )
        configServiceApiAddress.set(tryApi)
        //设置设置局部api的地址
        RetrofitUrlManager.getInstance().putDomain(ApiConfig.Value.API_DOMAIN_NAME, tryApi)
        //开始请求
        SlcApi.createSearchService(SearchService::class.java)
            .testLogin(
                SlcParam.newBuilder()
                    .put("username", TEST_API_USER_NAME)
                    .put("password", TEST_API_USER_NAME)
                    .put("tenantId", "000000")
                    .build()
            )
            .compose(SlcRxJavaUtils.applyOoAndroidSchedulers())
            .to(bindToLifecycle())
            .subscribe(object : SlcObserver<LoginResult>(
                SlcCallbackConfig.newBuilder()
                    .showToast(false)
                    .build()
            ) {
                override fun onSucceed(data: LoginResult) {
                    searchFinish(StringUtils.getString(R.string.api_label_searching_service_succeed))
                }

                override fun onFailed(errorCode: Int, errorMessage: String) {
                    //如果错误信息不是想要的，否则继续查询下一个ip地址
                    if (!isServiceByFailed(errorCode, errorMessage)) {
                        recursionSearch()
                        return
                    }
                    searchFinish(StringUtils.getString(R.string.api_label_searching_service_succeed))
                }

                private fun isServiceByFailed(errorCode: Int, errorMessage: String): Boolean {
                    return StrUtil.containsAny(errorMessage, TEST_API_USER_NAME)
                }

            })
    }

    /**
     * 搜索结束
     */
    private fun searchFinish(searchEndDialogMsg: String) {
        showSearchingDialog.value = false
        showSearchEndDialog.value = searchEndDialogMsg
    }

    fun save() {
        ApiSp.setServiceMode(configServiceMode)

        ApiSp.setApplyCacheApi(mainSwitchStatus.get())
        ApiSp.setServiceApiAddress(configServiceApiAddress.get())
        //RetrofitUrlManager.getInstance().setGlobalDomain(configServiceApiAddress.get())
        //配置到缓存中
        //重启
        ThreadUtils.runOnUiThreadDelayed({
            AppUtils.relaunchApp(true)
        }, 256)
    }
}